﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CoreUtils.WIL
{
    /// <summary>
    /// Conversion functions from WIL library
    /// </summary>
    public class Conversion
    {
        /// <summary>
        /// Convert image to gray scale mode
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toGrayScale(FVIL.Data.CFviImage src,
            double coeffR, double coeffG, double coeffB)
        {
            FVIL.Conversion.CFviGrayScale parser = new FVIL.Conversion.CFviGrayScale();
            int valid = FVIL.Conversion.CFviGrayScale.CheckValidity(src);
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate(0);

            parser.CoefficientBlue = coeffR;
            parser.CoefficientGreen = coeffG;
            parser.CoefficientRed = coeffB;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize image using using one threshold
        /// </summary>
        /// <param name="src"></param>
        /// <param name="threshold"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeThreshold(FVIL.Data.CFviImage src, int threshold)
        {
            FVIL.Conversion.CFviBinarize parser = new FVIL.Conversion.CFviBinarize();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarize.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarize.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Threshold = threshold;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize image using 2 threshold (low and high)
        /// </summary>
        /// <param name="src"></param>
        /// <param name="thresholdLow"></param>
        /// <param name="thresholdHigh"></param>
        public static FVIL.Data.CFviImage toBinaryBandThreshold(FVIL.Data.CFviImage src,
            int thresholdLow, int thresholdHigh)
        {
            FVIL.Conversion.CFviBinarizeBandThreshold parser =
                new FVIL.Conversion.CFviBinarizeBandThreshold();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeBandThreshold.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid,
                    "FVIL.Conversion.CFviBinarizeBandThreshold.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.ThresholdL = thresholdLow;
            parser.ThresholdH = thresholdHigh;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize image using discrimination method
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeDiscrimination(FVIL.Data.CFviImage src)
        {
            FVIL.Conversion.CFviBinarizeDiscrimination parser = new
                FVIL.Conversion.CFviBinarizeDiscrimination();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeDiscrimination.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid,
                    "FVIL.Conversion.CFviBinarizeDiscrimination.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize image using gradient
        /// </summary>
        /// <param name="src"></param>
        /// <param name="edgeFactor"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeGradient(FVIL.Data.CFviImage src, int edgeFactor)
        {
            FVIL.Conversion.CFviBinarizeGradient parser = new FVIL.Conversion.CFviBinarizeGradient();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeGradient.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarizeGradient.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.EdgeFactor = edgeFactor;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize using Kittler method
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeKittler(FVIL.Data.CFviImage src)
        {
            FVIL.Conversion.CFviBinarizeKittler parser = new FVIL.Conversion.CFviBinarizeKittler();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeKittler.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarizeKittler.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize using laplacien
        /// </summary>
        /// <param name="src"></param>
        /// <param name="edgeFactor"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeLaplacian(FVIL.Data.CFviImage src, int edgeFactor)
        {
            FVIL.Conversion.CFviBinarizeLaplacian parser = new FVIL.Conversion.CFviBinarizeLaplacian();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeLaplacian.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarizeLaplacian.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.EdgeFactor = edgeFactor;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize image using Niblack method
        /// </summary>
        /// <param name="src"></param>
        /// <param name="horzSize"></param>
        /// <param name="vertSize"></param>
        /// <param name="coeffK"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeNiblack(FVIL.Data.CFviImage src, int horzSize,
            int vertSize, double coeffK)
        {
            FVIL.Conversion.CFviBinarizeNiblack parser = new FVIL.Conversion.CFviBinarizeNiblack();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeNiblack.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarizeNiblack.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();

            parser.AreaHorzSize = horzSize;
            parser.AreaVertSize = vertSize;
            parser.CoefficientK = coeffK;
            parser.BorderMode = FVIL.BorderMode.None;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize using PTile method
        /// </summary>
        /// <param name="src"></param>
        /// <param name="rate"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizePTile(FVIL.Data.CFviImage src, int rate)
        {
            FVIL.Conversion.CFviBinarizePTile parser = new FVIL.Conversion.CFviBinarizePTile();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizePTile.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarizePTile.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Rate = rate;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binarize using Sauvola method
        /// </summary>
        /// <param name="src"></param>
        /// <param name="horzSize"></param>
        /// <param name="vertSize"></param>
        /// <param name="coeffK"></param>
        /// <param name="coeffR"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeSauvola(FVIL.Data.CFviImage src, int horzSize,
            int vertSize, double coeffK, double coeffR)
        {
            FVIL.Conversion.CFviBinarizeSauvola parser = new FVIL.Conversion.CFviBinarizeSauvola();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Conversion.CFviBinarizeSauvola.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Conversion.CFviBinarizeSauvola.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.AreaHorzSize = horzSize;
            parser.AreaVertSize = vertSize;
            parser.CoefficientK = coeffK;
            parser.CoefficientR = coeffR;
            parser.BorderMode = FVIL.BorderMode.None;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }

        /// <summary>
        /// Binary using shift average
        /// </summary>
        /// <param name="src"></param>
        /// <param name="horzSize"></param>
        /// <param name="vertSize"></param>
        /// <returns></returns>
        public static FVIL.Data.CFviImage toBinarizeShiftAverage(FVIL.Data.CFviImage src,
            int horzSize, int vertSize)
        {
            FVIL.Conversion.CFviBinarizeShiftAverage parser = new FVIL.Conversion.CFviBinarizeShiftAverage();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();

            int valid = FVIL.Conversion.CFviBinarizeShiftAverage.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid,
                    "FVIL.Conversion.CFviBinarizeShiftAverage.CheckValidity");

            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.AreaHorzSize = horzSize;
            parser.AreaVertSize = vertSize;

            try
            {
                parser.Execute();
            }
            catch (System.Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return dst;
        }
    }
}
